@@ -36,15 +36,6 @@ body { padding-top: 60px; } |
||
36 | 36 |
@extend .control-group.error; |
37 | 37 |
} |
38 | 38 |
|
39 |
-table.events { |
|
40 |
- .payload { |
|
41 |
- color: #999; |
|
42 |
- font-size: 12px; |
|
43 |
- //text-align: center; |
|
44 |
- font-family: monospace; |
|
45 |
- } |
|
46 |
-} |
|
47 |
- |
|
48 | 39 |
.select2 { |
49 | 40 |
float: none !important; |
50 | 41 |
margin-left: 0 !important; |
@@ -0,0 +1,31 @@ |
||
1 |
+// Sortable table headers |
|
2 |
+.table th a.selected { |
|
3 |
+ position: relative; |
|
4 |
+ text-decoration: underline; |
|
5 |
+ |
|
6 |
+ &.asc:after, &.desc:after { |
|
7 |
+ text-decoration: none; |
|
8 |
+ position: absolute; |
|
9 |
+ top: -5px; |
|
10 |
+ right: -12px; |
|
11 |
+ font-size: 1.2em; |
|
12 |
+ } |
|
13 |
+ |
|
14 |
+ &.asc:after { |
|
15 |
+ content: '\2193'; |
|
16 |
+ } |
|
17 |
+ |
|
18 |
+ &.desc:after { |
|
19 |
+ content: '\2191'; |
|
20 |
+ } |
|
21 |
+} |
|
22 |
+ |
|
23 |
+table.events { |
|
24 |
+ .payload { |
|
25 |
+ color: #999; |
|
26 |
+ font-size: 12px; |
|
27 |
+ //text-align: center; |
|
28 |
+ font-family: monospace; |
|
29 |
+ } |
|
30 |
+} |
|
31 |
+ |
@@ -1,8 +1,11 @@ |
||
1 | 1 |
class AgentsController < ApplicationController |
2 | 2 |
include DotHelper |
3 |
+ include SortableTable |
|
3 | 4 |
|
4 | 5 |
def index |
5 |
- @agents = current_user.agents.page(params[:page]) |
|
6 |
+ set_table_sort sorts: %w[name last_check_at last_event_at last_receive_at], default: { name: :asc } |
|
7 |
+ |
|
8 |
+ @agents = current_user.agents.preload(:scenarios, :controllers).reorder(table_sort).page(params[:page]) |
|
6 | 9 |
|
7 | 10 |
respond_to do |format| |
8 | 11 |
format.html |
@@ -0,0 +1,53 @@ |
||
1 |
+require 'active_support/concern' |
|
2 |
+ |
|
3 |
+module SortableTable |
|
4 |
+ extend ActiveSupport::Concern |
|
5 |
+ |
|
6 |
+ included do |
|
7 |
+ helper SortableTableHelper |
|
8 |
+ end |
|
9 |
+ |
|
10 |
+ protected |
|
11 |
+ |
|
12 |
+ def table_sort |
|
13 |
+ raise("You must call set_table_sort in any action using table_sort.") unless @table_sort_info.present? |
|
14 |
+ @table_sort_info[:order] |
|
15 |
+ end |
|
16 |
+ |
|
17 |
+ def set_table_sort(sort_options) |
|
18 |
+ valid_sorts = sort_options[:sorts] || raise("You must specify :sorts as an array of valid sort attributes.") |
|
19 |
+ default = sort_options[:default] || { valid_sorts.first.to_sym => :desc } |
|
20 |
+ |
|
21 |
+ if params[:sort].present? |
|
22 |
+ attribute, direction = params[:sort].downcase.split('.') |
|
23 |
+ unless valid_sorts.include?(attribute) |
|
24 |
+ attribute, direction = default.to_a.first |
|
25 |
+ end |
|
26 |
+ else |
|
27 |
+ attribute, direction = default.to_a.first |
|
28 |
+ end |
|
29 |
+ |
|
30 |
+ direction = direction.to_s == 'desc' ? 'desc' : 'asc' |
|
31 |
+ |
|
32 |
+ @table_sort_info = { |
|
33 |
+ order: { attribute.to_sym => direction.to_sym }, |
|
34 |
+ attribute: attribute, |
|
35 |
+ direction: direction |
|
36 |
+ } |
|
37 |
+ end |
|
38 |
+ |
|
39 |
+ module SortableTableHelper |
|
40 |
+ def sortable_column(attribute, name = attribute.humanize, default_direction = 'desc') |
|
41 |
+ selected = @table_sort_info[:attribute].to_s == attribute |
|
42 |
+ if selected |
|
43 |
+ direction = @table_sort_info[:direction] |
|
44 |
+ new_direction = direction.to_s == 'desc' ? 'asc' : 'desc' |
|
45 |
+ classes = "selected #{direction}" |
|
46 |
+ else |
|
47 |
+ classes = '' |
|
48 |
+ new_direction = default_direction |
|
49 |
+ end |
|
50 |
+ link_to(name, url_for(sort: "#{attribute}.#{new_direction}"), class: classes) |
|
51 |
+ end |
|
52 |
+ end |
|
53 |
+end |
@@ -1,8 +1,11 @@ |
||
1 | 1 |
class ScenariosController < ApplicationController |
2 |
+ include SortableTable |
|
2 | 3 |
skip_before_filter :authenticate_user!, :only => :export |
3 | 4 |
|
4 | 5 |
def index |
5 |
- @scenarios = current_user.scenarios.page(params[:page]) |
|
6 |
+ set_table_sort sorts: %w[name public], default: { name: :asc } |
|
7 |
+ |
|
8 |
+ @scenarios = current_user.scenarios.reorder(table_sort).page(params[:page]) |
|
6 | 9 |
|
7 | 10 |
respond_to do |format| |
8 | 11 |
format.html |
@@ -21,7 +24,9 @@ class ScenariosController < ApplicationController |
||
21 | 24 |
|
22 | 25 |
def show |
23 | 26 |
@scenario = current_user.scenarios.find(params[:id]) |
24 |
- @agents = @scenario.agents.preload(:scenarios).page(params[:page]) |
|
27 |
+ |
|
28 |
+ set_table_sort sorts: %w[name last_check_at last_event_at last_receive_at], default: { name: :asc } |
|
29 |
+ @agents = @scenario.agents.preload(:scenarios, :controllers).reorder(table_sort).page(params[:page]) |
|
25 | 30 |
|
26 | 31 |
respond_to do |format| |
27 | 32 |
format.html |
@@ -1,8 +1,12 @@ |
||
1 | 1 |
class ServicesController < ApplicationController |
2 |
+ include SortableTable |
|
3 |
+ |
|
2 | 4 |
before_filter :upgrade_warning, only: :index |
3 | 5 |
|
4 | 6 |
def index |
5 |
- @services = current_user.services.page(params[:page]) |
|
7 |
+ set_table_sort sorts: %w[provider name global], default: { provider: :asc } |
|
8 |
+ |
|
9 |
+ @services = current_user.services.reorder(table_sort).page(params[:page]) |
|
6 | 10 |
|
7 | 11 |
respond_to do |format| |
8 | 12 |
format.html |
@@ -1,6 +1,10 @@ |
||
1 | 1 |
class UserCredentialsController < ApplicationController |
2 |
+ include SortableTable |
|
3 |
+ |
|
2 | 4 |
def index |
3 |
- @user_credentials = current_user.user_credentials.page(params[:page]) |
|
5 |
+ set_table_sort sorts: %w[credential_name credential_value], default: { credential_name: :asc } |
|
6 |
+ |
|
7 |
+ @user_credentials = current_user.user_credentials.reorder(table_sort).page(params[:page]) |
|
4 | 8 |
|
5 | 9 |
respond_to do |format| |
6 | 10 |
format.html |
@@ -31,7 +31,7 @@ module AgentHelper |
||
31 | 31 |
end |
32 | 32 |
|
33 | 33 |
def agent_controllers(agent, delimiter = ', ') |
34 |
- unless agent.controllers.empty? |
|
34 |
+ if agent.controllers.present? |
|
35 | 35 |
agent.controllers.map { |agent| |
36 | 36 |
link_to(agent.name, agent_path(agent)) |
37 | 37 |
}.join(delimiter).html_safe |
@@ -1,11 +1,11 @@ |
||
1 | 1 |
<div class='table-responsive'> |
2 | 2 |
<table class='table table-striped'> |
3 | 3 |
<tr> |
4 |
- <th>Name</th> |
|
4 |
+ <th><%= sortable_column 'name', 'Name', 'asc' %></th> |
|
5 | 5 |
<th>Schedule</th> |
6 |
- <th>Last Check</th> |
|
7 |
- <th>Last Event Out</th> |
|
8 |
- <th>Last Event In</th> |
|
6 |
+ <th><%= sortable_column 'last_check_at', 'Last Check' %></th> |
|
7 |
+ <th><%= sortable_column 'last_event_at', 'Last Event Out' %></th> |
|
8 |
+ <th><%= sortable_column 'last_receive_at', 'Last Event In' %></th> |
|
9 | 9 |
<th>Events Created</th> |
10 | 10 |
<th>Working?</th> |
11 | 11 |
<th></th> |
@@ -12,9 +12,9 @@ |
||
12 | 12 |
|
13 | 13 |
<table class='table table-striped'> |
14 | 14 |
<tr> |
15 |
- <th>Name</th> |
|
15 |
+ <th><%= sortable_column 'name', 'Name', 'asc' %></th> |
|
16 | 16 |
<th>Agents</th> |
17 |
- <th>Public</th> |
|
17 |
+ <th><%= sortable_column 'public' %></th> |
|
18 | 18 |
<th></th> |
19 | 19 |
</tr> |
20 | 20 |
|
@@ -25,9 +25,9 @@ |
||
25 | 25 |
<div class='table-responsive'> |
26 | 26 |
<table class='table table-striped events'> |
27 | 27 |
<tr> |
28 |
- <th>Provider</th> |
|
29 |
- <th>Username</th> |
|
30 |
- <th>Global?</th> |
|
28 |
+ <th><%= sortable_column 'provider', 'Provider', 'asc' %></th> |
|
29 |
+ <th><%= sortable_column 'name', 'Name', 'asc' %></th> |
|
30 |
+ <th><%= sortable_column 'global', 'Global?' %></th> |
|
31 | 31 |
<th></th> |
32 | 32 |
</tr> |
33 | 33 |
|
@@ -14,8 +14,8 @@ |
||
14 | 14 |
|
15 | 15 |
<table class='table table-striped'> |
16 | 16 |
<tr> |
17 |
- <th>Name</th> |
|
18 |
- <th>Value</th> |
|
17 |
+ <th><%= sortable_column 'credential_name', 'Name', 'asc' %></th> |
|
18 |
+ <th><%= sortable_column 'credential_value', 'Value', 'asc' %></th> |
|
19 | 19 |
</tr> |
20 | 20 |
|
21 | 21 |
<% @user_credentials.each do |user_credential| %> |
@@ -0,0 +1,61 @@ |
||
1 |
+require 'spec_helper' |
|
2 |
+ |
|
3 |
+describe SortableTable do |
|
4 |
+ class SortableTestController |
|
5 |
+ attr_accessor :params |
|
6 |
+ |
|
7 |
+ def self.helper(foo) |
|
8 |
+ end |
|
9 |
+ |
|
10 |
+ include SortableTable |
|
11 |
+ |
|
12 |
+ public :set_table_sort |
|
13 |
+ public :table_sort |
|
14 |
+ end |
|
15 |
+ |
|
16 |
+ describe "#set_table_sort" do |
|
17 |
+ let(:controller) { SortableTestController.new } |
|
18 |
+ let(:default) { { column2: :asc }} |
|
19 |
+ let(:options) { { sorts: %w[column1 column2], default: default } } |
|
20 |
+ |
|
21 |
+ it "uses a default when no sort is given" do |
|
22 |
+ controller.params = {} |
|
23 |
+ controller.set_table_sort options |
|
24 |
+ controller.table_sort.should == default |
|
25 |
+ end |
|
26 |
+ |
|
27 |
+ it "applies the given sort when one is passed in" do |
|
28 |
+ controller.params = { sort: "column1.desc" } |
|
29 |
+ controller.set_table_sort options |
|
30 |
+ controller.table_sort.should == { column1: :desc } |
|
31 |
+ |
|
32 |
+ controller.params = { sort: "column1.asc" } |
|
33 |
+ controller.set_table_sort options |
|
34 |
+ controller.table_sort.should == { column1: :asc } |
|
35 |
+ |
|
36 |
+ controller.params = { sort: "column2.desc" } |
|
37 |
+ controller.set_table_sort options |
|
38 |
+ controller.table_sort.should == { column2: :desc } |
|
39 |
+ end |
|
40 |
+ |
|
41 |
+ it "ignores unknown directions" do |
|
42 |
+ controller.params = { sort: "column1.foo" } |
|
43 |
+ controller.set_table_sort options |
|
44 |
+ controller.table_sort.should == { column1: :asc } |
|
45 |
+ |
|
46 |
+ controller.params = { sort: "column1.foo drop tables" } |
|
47 |
+ controller.set_table_sort options |
|
48 |
+ controller.table_sort.should == { column1: :asc } |
|
49 |
+ end |
|
50 |
+ |
|
51 |
+ it "ignores unknown columns" do |
|
52 |
+ controller.params = { sort: "foo.asc" } |
|
53 |
+ controller.set_table_sort options |
|
54 |
+ controller.table_sort.should == default |
|
55 |
+ |
|
56 |
+ controller.params = { sort: ";drop table;.asc" } |
|
57 |
+ controller.set_table_sort options |
|
58 |
+ controller.table_sort.should == default |
|
59 |
+ end |
|
60 |
+ end |
|
61 |
+end |
@@ -55,6 +55,8 @@ RSpec.configure do |config| |
||
55 | 55 |
config.global_fixtures = :all |
56 | 56 |
config.treat_symbols_as_metadata_keys_with_true_values = true |
57 | 57 |
|
58 |
+ config.render_views |
|
59 |
+ |
|
58 | 60 |
config.include Devise::TestHelpers, :type => :controller |
59 | 61 |
config.include SpecHelpers |
60 | 62 |
config.include Delorean |